﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plat.WfProcess.Common;
using Plat.WfProcess.DataModel;

namespace Plat.WfProcess.Business
{
    /// <summary>
    /// 活动实例管理类
    /// </summary>
    internal class ActivityInstanceManager
    {
        #region ActivityInstanceManager 属性

        private ActivityInstanceRepository _activityInstanceRepository;
        private ActivityInstanceRepository activityInstanceRepository
        {
            get
            {
                if (_activityInstanceRepository == null)
                {
                    _activityInstanceRepository = new ActivityInstanceRepository();
                }
                return _activityInstanceRepository;
            }
        }
        #endregion
       
        #region ActivityInstanceManager 构造函数
        internal ActivityInstanceManager()
        {
        }
        #endregion

        #region ActivityInstanceManager 流程相关业务规则处理
        /// <summary>
        /// 创建活动实例的对象
        /// </summary>
        /// <param name="activity"></param>
        /// <param name="processInstance"></param>
        /// <returns></returns>
        internal ActivityInstanceEntity CreateActivityInstanceObject(ActivityEntity activity,
            ProcessInstanceEntity processInstance)
        {
            ActivityInstanceEntity instance = new ActivityInstanceEntity();
            instance.ActivityGUID = activity.ActivityGUID;
            instance.ActivityName = activity.ActivityName;
            instance.ActivityTypeID = (short)activity.NodeType;
            instance.GatewayDirectionTypeID = (short)activity.GatewayDirectionType;
            instance.ProcessGUID = activity.ProcessGUID;

            instance.ApplicationInstanceID = processInstance.ApplicationInstanceID;
            instance.ProcessInstanceGUID = processInstance.ProcessInstanceGUID;
            instance.ActivityInstanceGUID = Guid.NewGuid().ToString();
            instance.TokensRequired = 1;
            instance.TokensHad = 1;
            instance.CreatedDateTime = System.DateTime.Now;
            instance.State = (short)NodeStateEnum.Ready;
            instance.CanRenewInstance = 0;

            return instance;
        }

        internal ActivityInstanceEntity Select(string activityInstanceGUID)
        {
            return activityInstanceRepository.SelectById(activityInstanceGUID);
        }

        /// <summary>
        /// 判断有活动实例是否在运行状态
        /// </summary>
        /// <param name="activityGUID"></param>
        /// <returns></returns>
        internal ActivityInstanceEntity GetActivityWithRunningState(string processInstanceGUID,
            string activityGUID,
            ProcessModelDataContext wfLinqDataContext)
        {
            if (wfLinqDataContext != null)
            {
                activityInstanceRepository.LinqDataContext = wfLinqDataContext;
            }

            IList<ActivityInstanceEntity> instanceList = activityInstanceRepository.Select("ProcessInstanceGUID.ToString() == @0 and ActivityGUID.ToString() == @1 and State == @2",
                processInstanceGUID,
                activityGUID,
                (short)NodeStateEnum.Running);

            if (instanceList.Count == 1)
            {
                return instanceList[0];
            }
            else
            {
                return null;
            }
        }

        internal string Insert(ActivityInstanceEntity entity)
        {
            return Insert(entity, null);
        }

        internal string Insert(ActivityInstanceEntity entity, 
            ProcessModelDataContext wfLinqDataContext)
        {
            if (wfLinqDataContext != null)
            {
                activityInstanceRepository.LinqDataContext = wfLinqDataContext;
            }
            return activityInstanceRepository.Insert(entity).ActivityInstanceGUID.ToString();
        }

        internal void Update(ActivityInstanceEntity entity)
        {
            Update(entity, null);
        }

        internal void Update(ActivityInstanceEntity entity, ProcessModelDataContext wfLinqDataContext)
        {
            if (wfLinqDataContext != null)
            {
                activityInstanceRepository.LinqDataContext = wfLinqDataContext;
            }

            activityInstanceRepository.Update(entity);
        }

        /// <summary>
        /// 更新活动节点的Token数目
        /// </summary>
        /// <param name="activityInstanceGUID"></param>
        /// <param name="logonUser"></param>
        /// <param name="wfLinqDataContext"></param>
        internal void IncreaseTokensHad(string activityInstanceGUID,
            WfLogonUser logonUser,
            ProcessModelDataContext wfLinqDataContext)
        {
            ActivityInstanceEntity activityInstance = Select(activityInstanceGUID);
            activityInstance.TokensHad += 1;
            Update(activityInstance, wfLinqDataContext);
        }

        internal void Complete(string activityInstanceGUID,
            WfLogonUser logonUser)
        {
            Complete(activityInstanceGUID, logonUser, null);
        }

        internal void Complete(string activityInstanceGUID, 
            WfLogonUser logonUser,
            ProcessModelDataContext wfLinqDataContext)
        {
            ActivityInstanceEntity activityInstance = Select(activityInstanceGUID);
            activityInstance.State = (short)NodeStateEnum.Completed;
            activityInstance.IsActivityCompleted = 1;
            activityInstance.EndedByUserID = logonUser.UserID;
            activityInstance.EndedByUserName = logonUser.UserName;
            activityInstance.EndedDateTime = System.DateTime.Now;

            Update(activityInstance, wfLinqDataContext);
        }

        /// <summary>
        /// 删除活动实例
        /// </summary>
        /// <param name="activityInstanceGUID"></param>
        internal void Delete(string activityInstanceGUID)
        {
            Delete(activityInstanceGUID, null);
        }

        /// <summary>
        /// 删除活动实例
        /// </summary>
        /// <param name="activityInstanceGUID"></param>
        /// <param name="wfLinqDataContext"></param>
        internal void Delete(string activityInstanceGUID,
            ProcessModelDataContext wfLinqDataContext)
        {
            if (wfLinqDataContext != null)
            {
                activityInstanceRepository.LinqDataContext = wfLinqDataContext;
            }
            activityInstanceRepository.Delete(activityInstanceGUID);
        }
        #endregion
    }
}
